package com.alibaba.sdk.abstracts;

import com.alibaba.sdk.constant.SystemConstant;
import com.alibaba.sdk.model.entity.User;
import com.alibaba.sdk.util.EncryptUtil;
import com.alibaba.sdk.util.SessionUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.subject.WebSubject;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
import org.springframework.web.context.WebApplicationContext;

/**
 * 用于单元测试用户登录登出 注入session 信息
 *
 * @ author  Shawn(Shawn_0217@163.com)
 * @ date    2021/4/28 16:19
 * @ company Alibaba
 */

public class ShiroLoginAndLogoutAbstracts {

    @Autowired
    private SecurityManager securityManager;

    @Autowired
    private WebApplicationContext webApplicationContext;

    private Subject subject;

    private MockHttpServletRequest mockHttpServletRequest;

    private MockHttpServletResponse mockHttpServletResponse;

    /**
     * 由于单元测试未获取接口init request,response等信息
     * 所以需要mock request,response等信息,得以获取session
     * 用于shiro
     */
    @BeforeEach
    public void before() {
        mockHttpServletRequest = new MockHttpServletRequest(webApplicationContext.getServletContext());
        mockHttpServletResponse = new MockHttpServletResponse();
        MockHttpSession mockHttpSession = new MockHttpSession(webApplicationContext.getServletContext());
        mockHttpServletRequest.setSession(mockHttpSession);
        SecurityUtils.setSecurityManager(securityManager);
    }

    /**
     * 根据用户名密码登录
     *
     * @param username
     * @param password
     * @return
     */
    public String login(String username, String password) {
        subject = new WebSubject.Builder(mockHttpServletRequest, mockHttpServletResponse).buildWebSubject();
        // ShiroConfig ShiroRealm 做了用户登录认证 所以此密码需要加密传入
        UsernamePasswordToken token = new UsernamePasswordToken(username, EncryptUtil.getEncryptPassword(password), true);
        subject.login(token);
        ThreadContext.bind(subject);
        return SessionUtil.getUserInfo().getUsername();
    }

    /**
     * 根据用户名登录
     *
     * @param username
     * @return
     */
    public String login(String username) {
        String name = null;
        switch (username) {
            case SystemConstant.USERNAME_ADMIN:
                name = login(SystemConstant.USERNAME_ADMIN, SystemConstant.PASSWORD_ADMIN);
                break;
            case SystemConstant.USERNAME_NORMAL:
                name = login(SystemConstant.USERNAME_NORMAL, SystemConstant.PASSWORD_NORMAL);
                break;
            default:
                break;
        }
        return name;
    }

    /**
     * 用户登出
     */
    @AfterEach
    public void logout() {
        User userInfo = SessionUtil.getUserInfo();
        if (userInfo != null) {
            SessionUtil.logout();
        }
    }

}
